home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / DCLAP 4j / DBio / DSeqFile.cpp < prev    next >
Text File  |  1995-12-17  |  11KB  |  455 lines

  1. // DSeqFile.cp 
  2. // d.g.gilbert
  3.     
  4.  
  5. #include <ncbi.h>
  6. #include <dgg.h>
  7. #include <stdio.h>
  8. #include <DFile.h>
  9. #include "DSeqFile.h"
  10. #include "DSeqList.h"
  11. #include "ureadseq.h"
  12.  
  13.  
  14.  
  15. Global char* gOutputName = NULL;
  16.  
  17. Boolean DSeqFile::gWriteMasks = true;
  18. static char* kMaskName = "#Mask";
  19.  
  20. #if NEED_LATER
  21. // must be in scope of a DSeqFile:: method
  22. Local const  struct formatTable {
  23.   char  *name;
  24.   short num;
  25.   } formname[] = {
  26.     {"ig",  kIG},
  27.     {"stanford", kIG},
  28.     {"genbank", kGenBank},
  29.     {"gb", kGenBank},
  30.     {"nbrf", kNBRF},
  31.     {"embl", kEMBL},
  32.     {"gcg", kGCG},
  33.     {"uwgcg", kGCG},
  34.     {"dnastrider", kStrider},
  35.     {"strider", kStrider},
  36.     {"fitch", kFitch},
  37.     {"pearson", kPearson},
  38.     {"fasta", kPearson},
  39.     {"zuker", kZuker},
  40.     {"olsen", kOlsen},
  41.     {"phylip", kPhylip},
  42.     {"phylip3.2", kPhylip2},
  43.     {"phylip3.3", kPhylip3},
  44.     {"phylip3.4", kPhylip4},
  45.     {"phylip-interleaved", kPhylip4},
  46.     {"phylip-sequential", kPhylip2},
  47.     {"plain", kPlain},
  48.     {"raw", kPlain},
  49.     {"pir", kPIR},
  50.     {"codata", kPIR},
  51.     {"asn.1", kASN1},
  52.     {"msf", kMSF},
  53.     {"paup", kPAUP},
  54.     {"nexus", kPAUP},
  55.     {"pretty", kPretty},
  56.     {0,0}
  57.   };
  58. #endif
  59.  
  60. static char *gSeqFileFormats[] = { //DSeqFile::kMaxFormat+1
  61.         "IG|Stanford",
  62.         "GenBank|GB",
  63.         "NBRF",
  64.         "EMBL",
  65.         "GCG",
  66.         "DNAStrider",
  67.         "Fitch",
  68.         "Pearson|Fasta",
  69.         "Zuker [in only]",
  70.         "Olsen [in only]",
  71.         "Phylip3.2|Phylip2",
  72.         "Phylip|Phylip4",
  73.         "Plain|Raw",
  74.         "PIR|CODATA",
  75.         "MSF",
  76.         "ASN.1",
  77.         "PAUP|NEXUS",
  78.         "Pretty [out only]",
  79.         0};
  80.  
  81. const char* DSeqFile::FormatName(short index)
  82.     if (index<1 || index>18) return "";
  83.     else return gSeqFileFormats[index-1];
  84. }
  85.  
  86. short  DSeqFile::FormatFromName(const char* name)
  87. {
  88.     if (!name) return kUnknown;
  89.     long   i, len1, namelen= StrLen(name);
  90.     char      *form1, *form2;
  91.     if (namelen<2) return kUnknown;
  92.     for (i=0; i<kMaxFormat; i++) {
  93.         form1= (char*) gSeqFileFormats[i];
  94.         form2= StrChr(form1,'|'); 
  95.         if (form2) { len1= form2 - form1; form2++; }
  96.         else len1= StrLen( form1);
  97. #if 1
  98.         if (StrNICmp(name, form1,len1) == 0) return i+1;
  99.         else if (form2 && StrICmp(name, form2) == 0) return i+1;
  100. #else
  101.             // problem w/ Phylip matching Phylip3.2 not Phylip
  102.         if (StrNICmp(name, form1, namelen) == 0) return i+1;
  103.         else if (form2 && StrNICmp(name, form2, namelen) == 0) return i+1;
  104. #endif
  105.         }
  106.     return kUnknown;
  107. }
  108.  
  109.  
  110. char* DSeqFile::FixSeqID( char* s, short leftmargin)
  111. {
  112. #if 1
  113.     register char * cp, * ep;
  114.     for (cp= s; *cp && isspace(*cp); cp++) ;
  115.     for (ep= cp; *ep && !isspace(*ep); ep++) ;
  116.     if (ep>cp && ep[-1] == ',') ep--; // fix for fasta "name, #bases, # checksum"
  117.     if (*ep) *ep= 0;
  118.     return cp;
  119. #else
  120.     //s= StrDup(s);
  121.   short len = StrLen(s);
  122.     while (s[--len] == ' ' &&  len>0) ;
  123.     s[++len]= 0;
  124.     short i = Min( len-1, leftmargin);
  125.     while (s[i] == ' ' && i<len) i++;
  126.     if (i>0) s += i; //MemMove(s, s+i, len-i+1); //s= s+i;
  127.     //if (StrLen(s) > kNameWidth) s[kNameWidth]= 0;
  128.     return s;
  129. #endif
  130. }
  131.  
  132. short DSeqFile::SeqFileFormatWrapper( DFile* aFile) 
  133. {
  134.     long    skiplines = 0;
  135.     short    aFormat, err = 0;
  136.  
  137.     aFile->Open("r");  
  138.     aFormat= seqFileFormatFp( aFile->fFile, &skiplines, &err);
  139.     aFile->Close();  
  140.     return    aFormat;
  141. }
  142.  
  143.  
  144. short DSeqFile::ReadSeqFile( DFile* aFile, DSeqList* aSeqList) 
  145. {
  146.     char    seqid[256], *seqidptr, *bases, *seqlist;
  147.     long    skiplines = 0, skipi, seqlen;
  148.     short aFormat, atseq = 0, whichSeq = 0, nseq = 0, err = 0;
  149.     char  *defname;
  150.     Boolean notdone = true, needrewind = false;
  151.     DSequence* aSeq;
  152.     
  153.     aFile->OpenFile("r");    
  154.     aFormat = seqFileFormatFp( aFile->fFile, &skiplines, &err);
  155.     aFile->OpenFile(); // rewind
  156.     defname= FixSeqID( gDefSeqName, 0);
  157.     
  158.     switch (aFormat) {
  159.         case kUnknown:
  160.         case kNoformat:
  161.             aFile->CloseFile();
  162.             return aFormat;
  163.          
  164.             // all multi-pass (interleaved) formats go here !        
  165.         case kOlsen:
  166.         case kMSF:
  167.         case kPAUP:
  168.         case kPhylip2:
  169.         case kPhylip4:
  170.             needrewind = true;
  171.             aFile->CloseFile();
  172.             seqlist = listSeqs( aFile->GetName(), skiplines, aFormat, &nseq, &err);
  173.             MemFree(seqlist); 
  174.             break;
  175.         }
  176.         
  177.     skipi= skiplines;
  178.     while (notdone) {
  179.             // this one-pass thru gFileRef may well be buggy for current readSeq
  180.             // need to rewind file & count whichSeq++ for each sequence...?
  181.         if (needrewind) {
  182.             whichSeq++; 
  183.             atseq= 0; 
  184.             aFile->OpenFile("r");
  185.             skipi= skiplines;
  186.             }
  187.         else {
  188.             whichSeq = 1; 
  189.             atseq= 0;
  190.             }
  191.         seqlen = 0; seqidptr= seqid; *seqidptr= 0;
  192.         bases = readSeqFp( whichSeq, aFile->fFile, skipi, aFormat, &seqlen, 
  193.                                                         &atseq, &err, seqidptr);
  194.         skipi= 0; 
  195.         
  196.                 // install bases into new TSequence, and stick TSequence into list
  197.         if (bases) {
  198.             if (seqlen > 0) {
  199.                 char *name, * cp;
  200.                 Boolean ismask= false;
  201.                 
  202.                 if (*seqidptr != 0) {
  203.                     if ( (cp= StrStr(seqidptr, kMaskName)) != NULL) {
  204.                         ismask= true;
  205.                         *cp= 0;
  206.                         }
  207.                     name= FixSeqID( seqidptr, 0);
  208.                     }
  209.                 else 
  210.                     name= defname;
  211.                     
  212.                 if (ismask) {
  213.                     aSeq= aSeqList->FindNamedSeq( name);
  214.                     if (aSeq) {
  215.                         // convert mask...
  216.                         register char *mp;
  217.                         for (mp= bases; *mp; mp++) { 
  218.                             *mp -= '?'; // to zero relative
  219.                             *mp |= 0x80; // add high bit
  220.                             }
  221.                         aSeq->SetMasks( bases);
  222.                         }
  223.                     }
  224.                 else {
  225.                     aSeq = MakeSequence( name, bases, NULL, 0); //gFileRef->moddate
  226.                     aSeqList->InsertLast(aSeq);
  227.                     }
  228.                 }
  229.             else notdone= false;
  230.             MemFree(bases); // readSeq made this ptr w/ malloc call... MakeSeq copies this data... 
  231.             }
  232.         else notdone= false; // nodata -- if format=0, no data is read
  233.             
  234.         if (needrewind) notdone &= (whichSeq < nseq); // stop now
  235.         else notdone &= !aFile->Eof();  
  236.         }
  237.         
  238.     aFile->CloseFile();
  239.     return aFormat;
  240. }
  241.  
  242.  
  243.  
  244.  
  245. void    DSeqFile::WriteSeqHeader( DFile* aFile,  
  246.                                 short format, short nseqs, long nbases, char* outputName,
  247.                                 Boolean& needSameSize, Boolean& isInterleaved)
  248. {
  249.     const char *kASN1headline = "Bioseq-set ::= {\nseq-set {\n";
  250.     char    line[256], name[64];
  251.     
  252.     // this is a ureadseq.h call
  253.     // need to do somewhere once, then let user set prefs...
  254.  
  255. #define gPrettyInit1(p) { \
  256.   p.isactive=false;\
  257.   p.baseonlynum=true;\
  258.   p.numline= p.atseq= 0;\
  259.   p.numright= p.numtop= true; \
  260.   p.numleft= p.numbot= false;\
  261.   p.nameright= true; \
  262.   p.nameleft= p.nametop= false;\
  263.   p.noleaves= p.domatch= p.degap= false;\
  264.   p.matchchar='.';\
  265.   p.gapchar='-';\
  266.   p.namewidth=8;\
  267.   p.numwidth=5;\
  268.   p.interline=1;\
  269.   p.spacer=10;\
  270.   p.seqwidth=50;\
  271.   p.tab=0; }
  272.  
  273.     gPrettyInit1(gPretty);
  274.     //gPretty.interline= 2; // not active, along w/ numtop,numbot,nametop...
  275.     // need to work into this class
  276.     
  277.     
  278.         
  279.     needSameSize= false;
  280.     isInterleaved= false;
  281.     aFile->Open("a"); 
  282.  
  283.     if (outputName) StrNCpy( name, outputName, 63);
  284.     else StrCpy( name, DFileManager::kUntitled);
  285.     
  286.     switch (format) {
  287.         case kPIR:
  288.             aFile->WriteLine( "\\\\\\\n");
  289.             break;
  290.         case kASN1:
  291.             aFile->WriteLine( (char*)kASN1headline);
  292.             break;
  293.  
  294.         case kMSF:     // this is for top of interleaved file
  295.             {
  296.             isInterleaved= true;
  297.          unsigned long checksum = 0, checkall = 0;
  298.             //checksum= GCGchecksum(seq, seqlen, &checkall);
  299.             sprintf(line,"\n %s  MSF: %d  Type: N  June 01, 1776 12:00  Check: %d ..\n\n",
  300.                                         name, nbases, checkall);
  301.             aFile->WriteLine( line);
  302.             }
  303.             break;
  304.  
  305.         case kPhylip2:     
  306.             isInterleaved= false;
  307.             goto allphyl;
  308.             break;
  309.  
  310.         case kPhylip4:      
  311.             isInterleaved= true;
  312.         allphyl:
  313.             {
  314. //    if (phylvers >= 4) fprintf(foo," %d %d\n", seqout, seqlen);
  315. //    else fprintf(foo," %d %d YF\n", seqout, seqlen);
  316.             if (isInterleaved) sprintf( line, " %d %d F\n", nseqs, nbases);  
  317.             else sprintf( line, " %d %d FI \n", nseqs, nbases);  
  318.             aFile->WriteLine( line);
  319.             needSameSize= true;
  320.             }
  321.             break;
  322.  
  323.         case kPAUP:
  324.             isInterleaved= true;
  325.             needSameSize= true;
  326.             aFile->WriteLine( "#NEXUS\n");
  327.             sprintf( line,"[%s -- data title]\n\n", name);
  328.             aFile->WriteLine( line);
  329.             break;
  330.  
  331.         case kPretty:
  332.             isInterleaved= true;
  333.             gPretty.isactive= true;
  334.             break;
  335.             
  336.         default:
  337.             break;
  338.         }
  339.         
  340.     aFile->CloseFile();
  341. }
  342.  
  343.  
  344.  
  345. void    DSeqFile::DoInterleave( DFile* toFile, DFile* fromFile, 
  346.                                 short outform, short seqtype, short nseqs, long nbases,
  347.                                 short nlines, short noutindex, long* outindex)
  348. {
  349.     short        leaf, iline, iseq;
  350.     char        *cp, line[256];
  351.     
  352.     toFile->Open("a");
  353.     fromFile->Open("r");
  354.     
  355.     for (leaf=0; leaf<nlines; leaf++) {
  356.     
  357.         if (outform == kMSF && leaf == 1) { // do after writing seq names
  358.             toFile->WriteLine( "//\n\n");
  359.             }
  360.             
  361.         if (outform == kPAUP && leaf==1) { // do after writing seq names
  362.             switch (seqtype) {
  363.                 case DSequence::kDNA     : cp= "dna"; break;
  364.                 case DSequence::kRNA     : cp= "rna"; break;
  365.                 case DSequence::kNucleic : cp= "dna"; break;
  366.                 case DSequence::kAmino   : cp= "protein"; break;
  367.                 case DSequence::kOtherSeq: cp= "dna"; break;
  368.                 }
  369.             toFile->WriteLine( "\nbegin data;\n");
  370.             sprintf(line," dimensions ntax=%d nchar=%d;\n", nseqs, nbases); 
  371.             toFile->WriteLine( line);
  372.             sprintf(line," format datatype=%s interleave missing=%c", cp, gPretty.gapchar); // gapchar == indelHard ??? 
  373.             toFile->WriteLine( line);
  374.             //if (gPretty.domatch) { sprintf(line," matchchar=%c", gPretty.matchchar); 
  375.                 //Mwrite( toFile, line); }
  376.             toFile->WriteLine( ";\n  matrix\n");
  377.             }
  378.  
  379.         for (iseq=0; iseq<noutindex; iseq++) {
  380.             fromFile->SetDataMark( outindex[iseq]);
  381.             
  382.             for (iline=0; iline<=leaf; iline++)
  383.                 if (fromFile->ReadLine( line, 256) != 0) *line= 0;
  384.                 
  385.             if (fromFile->Tell() <= outindex[iseq+1])
  386.                 toFile->WriteLine( line, false);  //remember- ReadLine a.k.a fgets retains newline
  387.             }
  388.  
  389.      for (iline=0; iline<gPretty.interline; iline++)
  390.         toFile->WriteLine("\n"); //LineEnd 
  391.             
  392.         }
  393.         
  394.     fromFile->Close();
  395.     toFile->Close();
  396. }
  397.  
  398.  
  399. void    DSeqFile::WriteSeqTrailer( DFile* aFile,
  400.                                 short format, short /*nseqs*/, short /*nlinesperseq*/, long /*nbases*/)
  401. {
  402.     switch (format) {
  403.   
  404.       case kASN1:  
  405.             aFile->Open("a"); 
  406.             aFile->WriteLine("} }\n"); 
  407.             aFile->Close(); 
  408.             break;
  409.     
  410.       case kPAUP:    
  411.             aFile->Open("a"); 
  412.             aFile->WriteLine(";\n  end;\n");
  413.             aFile->Close(); 
  414.             break;    
  415.         }
  416. }
  417.  
  418.  
  419.  
  420. void DSeqFile::WriteSeqWrapper( DFile* aFile,
  421.                                     char *seq, long seqlen, short outform, char *seqid)
  422.     if (!aFile->IsOpen()) aFile->Open("a");
  423.     seqid= StrDup(seqid);
  424.     char* cp= FixSeqID(seqid, 0);
  425.     gLinesPerSeqWritten= writeSeq( aFile->fFile, seq, seqlen, outform, cp);
  426.     MemFree(seqid);
  427.     //aFile->Close(); //?? want left open for appending by caller ? e.g., seqmail
  428. }  
  429.  
  430. void DSeqFile::WriteMaskWrapper( DFile* aFile,
  431.                                     char *mask, long seqlen, short outform, char *seqid)
  432.     char maskid[128];
  433.     if (!aFile->IsOpen()) aFile->Open("a"); 
  434.     seqid= StrDup(seqid);
  435.     char* cp= FixSeqID(seqid, 0);
  436.     StrNCpy( maskid, cp, sizeof(maskid)-5);
  437.     StrNCat( maskid, kMaskName, sizeof(maskid));
  438.     MemFree(seqid);
  439.         //     massage mask into writable form
  440.     mask= StrDup(mask); 
  441.     Boolean hasdata= false;
  442.     for (cp= mask; *cp; cp++) { 
  443.         *cp &= 0x7F; // drop hi bit
  444.         if (*cp != 0) hasdata= true;
  445.         *cp += '?';  // set 0 == '?', mask range is mostly 'A-Za-z'
  446.      }
  447.     if (hasdata)
  448.         gLinesPerSeqWritten= writeSeq( aFile->fFile, mask, seqlen, outform, maskid);
  449.     MemFree(mask);
  450. }  
  451.  
  452.